﻿using System;
using System.Collections.Generic;
using System.Text;
using com.lover.astd.common.logic;
using com.lover.astd.common.model;
using com.lover.astd.common.model.attack;

namespace com.lover.astd.common.logicexe.battle
{
    public class AttackExe : ExeBase
    {
        public AttackExe() { _name = ConfigStrings.S_Attack; _readable = ConfigStrings.SR_Attack; }
        public override void init_data() 
        {
            if(_user._inNewArea) ServiceFactory.getBattleManager().getNewAreaInfo(_proto, _logger, _user);
            refreshUi();
        }
        public override long execute()
        {
            BattleMgr mgr = ServiceFactory.getBattleManager(); 
            Dictionary<string, string> conf = getConfig();
            if (!conf.ContainsKey(ConfigStrings.enabled) || !(conf[ConfigStrings.enabled].ToLower().Equals("true"))) return an_hour_later();
            bool _enable_cityevent = conf.ContainsKey(ConfigStrings.city_event) && conf[ConfigStrings.city_event].ToLower().Equals("true");
            bool _enable_gongjian = conf.ContainsKey(ConfigStrings.gongjian) && conf[ConfigStrings.gongjian].ToLower().Equals("true");

            bool _enable_attack = conf.ContainsKey(ConfigStrings.enable_attack) && conf[ConfigStrings.enable_attack].ToLower().Equals("true");
            bool _enable_get_extra_order = conf.ContainsKey(ConfigStrings.get_extra_order) && conf[ConfigStrings.get_extra_order].ToLower().Equals("true");

            bool _attack_npc = conf.ContainsKey(ConfigStrings.attack_npc) && conf[ConfigStrings.attack_npc].ToLower().Equals("true");
            bool _use_token = conf.ContainsKey(ConfigStrings.use_token) && conf[ConfigStrings.use_token].ToLower().Equals("true");
            bool _auto_move = conf.ContainsKey(ConfigStrings.auto_move) && conf[ConfigStrings.auto_move].ToLower().Equals("true");
            bool _do_jail_tech = conf.ContainsKey(ConfigStrings.jail_tech) && conf[ConfigStrings.jail_tech].ToLower().Equals("true");
            bool _attack_only_not_injail = conf.ContainsKey(ConfigStrings.not_injail) && conf[ConfigStrings.not_injail].ToLower().Equals("true");

            int _level_min = 0, _level_max = 0, _target_minScore = 5000;
            int _reserve_token = 0;
            if (conf.ContainsKey(ConfigStrings.level_min)) Int32.TryParse(conf[ConfigStrings.level_min], out _level_min);
            if (conf.ContainsKey(ConfigStrings.level_max)) Int32.TryParse(conf[ConfigStrings.level_max], out _level_max);
            if (conf.ContainsKey(ConfigStrings.min_score)) Int32.TryParse(conf[ConfigStrings.min_score], out _target_minScore);
            if (_target_minScore == 0) _target_minScore = 5000;
            if (conf.ContainsKey(ConfigStrings.attack_reserve_token)) Int32.TryParse(conf[ConfigStrings.attack_reserve_token], out _reserve_token);
            if (!conf.ContainsKey(ConfigStrings.attack_reserve_token_enable)
                || !(conf[ConfigStrings.attack_reserve_token_enable].ToLower().Equals("true"))) _reserve_token = 0;
            string move_target = "";
            if (conf.ContainsKey(ConfigStrings.move_target)) move_target = conf[ConfigStrings.move_target];

            User u = _user;
            if (!u._inNewArea) return an_hour_later(); // 那么还没到新地区, 忽略

            mgr.getNewAreaInfo(_proto, _logger, _user);
            mgr.getUserTokens(_proto, _logger, _user);
            mgr.getJailInfo(_proto, _logger, _user, _do_jail_tech, getGoldAvailable());
            if (u._attack_selfCityId == 0) return an_hour_later(); // 如果不存在自己区域, 那么还没到新地区, 忽略
            if (u._attack_cityHpRecoverCd > 0) return u._attack_cityHpRecoverCd;
            if (_enable_cityevent)
            {
                // 先做城池事件
                // 如果可以领取城池事件奖励, 那么来领奖
                if (u._attack_can_reward_cityevent > 0)
                {
                    if (!mgr.getCityEventAward(_proto, _logger)) return immediate(); //如果拿取奖励失败, 立刻返回继续拿
                    else u._attack_remain_cityevent_num--;
                }
                if (u._attack_remain_cityevent_num > 0)
                {
                    // 如果正在做城池事件, 那么什么都做不了(迁移/打人都不行), 返回
                    if (u._attack_current_cityevent_cdtime > 0)
                    {
                        logInfo("正在执行城池事件, 等待执行完毕");
                        return u._attack_current_cityevent_cdtime;
                    }
                    // 如果没有正在做城池事件, 那么开始做
                    logInfo(String.Format("城池事件还剩[{0}]个, 开始接受事件", u._attack_remain_cityevent_num));
                    bool accept = mgr.acceptCityEvent(_proto, _logger, _user);
                    if (!accept) return immediate(); //如果接受事件失败, 立刻返回继续
                    if (u._attack_current_cityevent_cdtime > 0) return u._attack_current_cityevent_cdtime;
                }
            }
            if (_enable_get_extra_order) mgr.handleTransferInfo(_proto, _logger, _user);

            u._attack_gongjian_status = -1;
            u._attack_nationBattleCd = -1;
            if (_enable_gongjian)
            {
                mgr.getNationBattleInfo(_proto, _logger, _user);
                if (u._attack_gongjian_status == 3)
                {
                    mgr.getNationBattleReward(_proto, _logger);
                    mgr.getNationBattleInfo(_proto, _logger, _user);
                }
            }

            if (u.AttackOrders <= _reserve_token)
            {
                if (_enable_gongjian)
                {
                    if (u._attack_gongjian_status == 0) return smaller_time(next_hour(), u._attack_nationBattleCd);
                    else if (u._attack_gongjian_status == 2 || u._attack_gongjian_status == 3) return smaller_time(next_hour(), u._attack_nationBattleRemainTime);
                }
                else return next_hour();
            }

            if (u.TokenCdFlag)
            {
                if (_enable_gongjian)
                {
                    if (u._attack_gongjian_status == 0) return smaller_time(next_hour(), u._attack_nationBattleCd);
                    else if (u._attack_gongjian_status == 2 || u._attack_gongjian_status == 3) return smaller_time(next_hour(), u._attack_nationBattleRemainTime);
                }
                else return u.TokenCdTime;
            }
            mgr.getBattleScoreInfo(_proto, _logger, _user);
            for (int i = 0; i < u._attack_battleScore_awardGot.Length; i++)
            {
                if (u._attack_battleScore_awardGot[i] == 0) break; // if i cannot get reward, i+1 sure cannot, so break the loop
                if (u._attack_battleScore_awardGot[i] == 1)
                {
                    mgr.getBattleScoreAward(_proto, _logger, i + 1);
                }
            }

            if (_enable_attack && u._attack_battleScore >= _target_minScore)
            {
                // if all rewards have got, execute next day
                if (u._attack_battleScore_awardGot[u._attack_battleScore_awardGot.Length - 1] == 2)
                {
                    if (_enable_gongjian)
                    {
                        if (u._attack_gongjian_status == 0) return smaller_time(next_day(), u._attack_nationBattleCd);
                        else if (u._attack_gongjian_status == 2 || u._attack_gongjian_status == 3) return smaller_time(next_day(), u._attack_nationBattleRemainTime);
                    }
                    else return next_day();
                }
                else
                {
                    for (int i = 0; i < u._attack_battleScore_awardGot.Length; i++)
                    {
                        if (u._attack_battleScore_awardGot[i] == 0) break; // if i cannot get reward, i+1 sure cannot, so break the loop
                        if (u._attack_battleScore_awardGot[i] == 1)
                        {
                            mgr.getBattleScoreAward(_proto, _logger, i + 1);
                        }
                    }
                    if (_enable_gongjian)
                    {
                        if (u._attack_gongjian_status == 0) return smaller_time(next_day(), u._attack_nationBattleCd);
                        else if (u._attack_gongjian_status == 2 || u._attack_gongjian_status == 3) return smaller_time(next_day(), u._attack_nationBattleRemainTime);
                    }
                    else return next_day();
                }
            }
            // 如果_nationBattleCd
            if (_enable_gongjian)
            {
                if (u._attack_gongjian_status == 0) // 如果没有在集结
                {
                    if (_enable_attack && u._attack_battleScore >= _target_minScore)
                        return smaller_time(next_day(), u._attack_nationBattleCd);// 看下次攻坚战和下一天谁早, 用谁 
                }
                else if (u._attack_gongjian_status == 2 || u._attack_gongjian_status == 3)
                {
                    if (_enable_attack && u._attack_battleScore >= _target_minScore)
                        return smaller_time(next_day(), u._attack_nationBattleRemainTime);
                }
            }
            else // 如果不攻坚战
            {
                if (_enable_attack && u._attack_battleScore >= _target_minScore) return next_day(); // 并且已经达到了分数, 那么下一天再来
            }

            AreaInfo area = null;
            if (_auto_move) area = mgr.getNextMoveArea(_proto, _logger, _user, move_target);
            if (area != null && u._attack_transfer_cd == 0)
            {
                int move_result = mgr.moveToArea(_proto, _logger, _user, area.areaid);
                if (move_result == 2) return 10 * 60 * 1000; // 10分钟后
                if (move_result == 0)
                {
                    if (!_enable_attack) return 60 * 1000; // 移动cd 1分钟
                    if (_enable_gongjian)
                    {
                        if (u._attack_battleScore < _target_minScore)
                        {
                            if (_use_token) mgr.useToken(_proto, _logger, _user, _target_minScore);
                            long protect_cd = mgr.find_and_attack(_proto, _logger, _user, _reserve_token, _attack_only_not_injail,
                                _attack_npc, _level_min, _level_max);
                            mgr.doJail(_proto, _logger, _user, _do_jail_tech, getGoldAvailable());
                            if (protect_cd > 65 * 1000) protect_cd = 65 * 1000;
                            if (u.AttackOrders <= _reserve_token || u.TokenCdFlag) return 65 * 1000;
                            else if (protect_cd < 0) // 没人可打, 等移动
                            {
                                return 65 * 1000;
                            }
                            else if (protect_cd > 0) return protect_cd; // 移动cd1分钟
                            else return immediate();
                        }
                        else return 65 * 1000; // 移动cd1分钟
                    }
                    else
                    {
                        if (u._attack_battleScore < _target_minScore)
                        {
                            if (_use_token) mgr.useToken(_proto, _logger, _user, _target_minScore);
                            long protect_cd = mgr.find_and_attack(_proto, _logger, _user, _reserve_token, _attack_only_not_injail,
                                _attack_npc, _level_min, _level_max);
                            mgr.doJail(_proto, _logger, _user, _do_jail_tech, getGoldAvailable());
                            if (protect_cd > 60 * 1000) protect_cd = 60 * 1000;
                            else if (protect_cd < 0) // 没人可打, 等移动
                            {
                                return 65 * 1000;
                            }
                            else if (protect_cd > 0) return protect_cd; // 移动cd1分钟
                            else return immediate();
                        }
                        else return 65 * 1000; // 移动cd1分钟
                    }
                }
                else return 60 * 1000; // 没移动成功 1分钟后再试
            }
            else if (_enable_attack) // 没有可移动的区域, 那么本地开打
            {
                if (_enable_gongjian) // 已经到集结目的地
                {
                    if (u._attack_battleScore < _target_minScore)
                    {
                        if (_use_token) mgr.useToken(_proto, _logger, _user, _target_minScore);
                        long protect_cd = mgr.find_and_attack(_proto, _logger, _user, _reserve_token, _attack_only_not_injail,
                            _attack_npc, _level_min, _level_max);
                        mgr.doJail(_proto, _logger, _user, _do_jail_tech, getGoldAvailable());
                        if (protect_cd > 0) return protect_cd;
                        else if (u.AttackOrders <= _reserve_token) return next_hour();
                        else if (u.TokenCdFlag) return u.TokenCdTime;
                        else if (protect_cd < 0) // 没人可打, 等下个小时看有没有人
                        {
                            return next_hour();
                        }
                        else return immediate();
                    }
                    else return 300 * 1000; // 已到目的地, 5分钟刷新一次
                }
                else
                {
                    if (u._attack_battleScore < _target_minScore)
                    {
                        if (_use_token) mgr.useToken(_proto, _logger, _user, _target_minScore);
                        long protect_cd = mgr.find_and_attack(_proto, _logger, _user, _reserve_token, _attack_only_not_injail,
                            _attack_npc, _level_min, _level_max);
                        mgr.doJail(_proto, _logger, _user, _do_jail_tech, getGoldAvailable());
                        if (protect_cd > 0) return protect_cd;
                        else if (u.TokenCdFlag) return u.TokenCdTime;
                        else if (u.AttackOrders <= _reserve_token) return next_hour();
                        else if (protect_cd < 0) // 没人可打, 等下个小时看有没有人
                        {
                            return next_hour();
                        }
                        else return immediate();
                    }
                    else return next_day();
                }
            }
            else return an_hour_later(); // 没地方移动并且不打架, 那么1小时后继续
            return immediate();
        }
    }
}
